<?php

namespace services;


 class RedisService
{
    private static $redis; // redis实例 禁止外部调用
    private static $instance; // 单例实例
    public $project = 'samTfrs2'; // 项目名
    /**
     * 禁止外部new
     * Redis constructor.
     */
    private function __construct(){
        if(!self::$redis) {
            self::$redis = getRedis();
        }
    }

    /**
     * 获取对象实例
     * @return Redis
     * coding_date 2019/9/17 11:20
     * developer YangYunTian
     */
    public static function getInstance() {
        if(!self::$redis) {
            self::$instance = new self();
        }
        return self::$instance;
    }


    /**
     * 格式化key
     * @param string $dir
     * @param string $key
     * @return string
     * coding_date 2019/9/17 11:26
     * developer YangYunTian
     */
    private function parseKey($dir='', $key='') {
        return "{$this->project}:$dir:$key";
    }

    /**
     * @name: 设置过期时间
     * @Author: Sam
     * @Date: 2020-07-06 14:22:15
     * @msg: 
     * @param {type} 
     * @return: 
     */
    public function set_expire($dir='',$key,$time){
        if(empty($dir) || empty($key) || empty($time)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->expire($key,$time);
    }

        /**
     * @name: 获取key的生存时间
     * @Author: Sam
     * @Date: 2020-07-06 14:22:15
     * @msg: 
     * @param {type} 
     * @return: 
     */
    public function set_ttl($dir='',$key){
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->ttl($key);
    }

            /**
     * @name: 获取key的生存时间
     * @Author: Sam
     * @Date: 2020-07-06 14:22:15
     * @msg: 
     * @param {type} 
     * @return: 
     */
    public function setnx($dir='',$key,$value){
        if(empty($dir) || empty($key) || empty($value)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->setnx($key,$value);
    }
    
    /**
     * Redis string类型 set方法
     * @param string $dir
     * @param string $key
     * @param string $value
     * @param int $timeout
     * @return boolean
     * coding_date 2019/9/17 11:26
     * developer YangYunTian
     */
    public function set($dir='', $key='', $value='', $timeout=0) {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        if(empty($timeout)) {
            return self::$redis->set($key, $value);
        }else {
            return self::$redis->set($key, $value, $timeout);
        }
    }

        /**
     * Hash类型 setall方法
    * @param string $dir
     * @param string $key
     * @param string $hashKey
     * @param string $value
     * @return bool|int
     * coding_date 2019/10/13 21:42
     * developer YangYunTian
     */
    public function hMset($dir='', $key='', $value='') {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->hMset($key, $value);
    }


    /**
     * Redis string类型 get方法
     * @param string $dir
     * @param string $key
     * @return bool|string
     * coding_date 2019/9/17 11:30
     * developer YangYunTian
     */
    public function get($dir='', $key='') {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->get($key);
    }

    /**
     * Redis string类型 incr方法
     * @param string $dir
     * @param string $key
     * @return bool
     * coding_date 2019/9/17 11:36
     * developer YangYunTian
     */
    public function incr($dir='', $key='') {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->incr($key);
    }

    /**
     * Redis string类型 exists方法
     * @param string $dir
     * @param string $key
     * @return bool|int
     * coding_date 2019/10/8 10:28
     * developer YangYunTian
     */
    public function exists($dir='', $key='') {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->exists($key);
    }

    /**
     * 获取redis值， 如果没有并存储
     * @param string $dir
     * @param string $key
     * @param array $options
     * @param $func
     * @param int $timeout
     * @return bool|string
     * coding_date 2019/10/9 15:25
     * developer YangYunTian
     */
    public function getOrSet($dir='', $key='', $options=[], $func, $timeout=60) {
        if(empty($dir) || empty($key)) return false;
        if($this->exists($dir, $key)) {
            return $this->get($dir, $key);
        }else {
            $value = $func(self::$instance, $options);
            $this->set($dir, $key, $value, $timeout);
            return $value;
        }
    }


    /**
     * list类型 插入一个item
     * @param string $dir
     * @param string $key
     * @param string $value
     * @param int $about 0:左进 1:右进
     * @return bool|int
     * coding_date 2019/10/13 20:54
     * developer YangYunTian
     */
    public function l_push($dir='', $key='', $value='', $about=0) {
        if(empty($dir) || empty($key) || empty($value)) return false;
        $key = $this->parseKey($dir, $key);
        if($about == 1) {
            return self::$redis->rPush($key, (string)$value);
        }else {
            return self::$redis->lPush($key, (string)$value);
        }
    }

    /**
     * list类型 取出一个item
     * @param string $dir
     * @param string $key
     * @param int $about 0-左出 1-右出
     * @return bool|string
     * coding_date 2019/11/19 19:38
     * developer YangYunTian
     */
    public function l_pop($dir='', $key='', $about=1) {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        if($about == 1) {
            return self::$redis->rPop($key);
        }else {
            return self::$redis->lPop($key);
        }
    }

    /**
     * list类型 item是否存在
     * @param string $dir
     * @param string $key
     * @param string $value
     * @return bool
     * coding_date 2019/10/13 21:12
     * developer YangYunTian
     */
    public function l_exists($dir='', $key='', $value='') {
        if(empty($dir) || empty($key) || empty($value)) return false;
        $key = $this->parseKey($dir, $key);
        $list = self::$redis->lRange($key, 0, -1);
        return in_array($value, $list) ? true : false;
    }

    /**
     * list类型 返回list长度
     * @param string $dir
     * @param string $key
     * @return bool
     * coding_date 2019/10/13 21:14
     * developer YangYunTian
     */
    public function l_size($dir='', $key='') {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->lLen($key);
    }

    /**
     * 所有类型 删除redis键
     * @param string $dir
     * @param string $key
     * @return bool
     * coding_date 2019/10/13 21:14
     * developer YangYunTian
     */
    public function delete($dir='', $key='') {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->del($key);
    }

    /**
     * list类型 为空则读取并存储
     * @param string $dir
     * @param string $key
     * @param array $options
     * @param $func
     * @return bool
     * coding_date 2019/10/13 21:36
     * developer YangYunTian
     */
    public function l_get_or_set($dir='', $key='', $options=[], $func) {
        if(empty($dir) || empty($key)) return false;
        if($this->l_size($dir, $key) == 0) {
            $list = $func(self::$redis, $options);
            if(!empty($list)) {
                foreach($list as $item) {
                    $this->l_push($dir, $key, $item);
                }
            }
        }
    }

    /**
     * Hash类型 get方法
     * @param string $dir
     * @param string $key
     * @param string $name
     * @return bool|string
     * coding_date 2019/10/13 21:42
     * developer YangYunTian
     */
    public function h_get($dir='', $key='', $hashKey='') {
        if(empty($dir) || empty($key) || empty($hashKey)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->hGet($key, $hashKey);
    }

    /**
     * Hash类型 hGetALL方法
     * @param string $dir
     * @param string $key
     * @return array|bool
     * coding_date 2019/11/27 16:13
     * developer YangYunTian
     */
    public function h_getAll($dir='', $key='') {
        if(empty($dir) || empty($key)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->hGetAll($key);
    }

    /**
     * Hash类型 set方法
    * @param string $dir
     * @param string $key
     * @param string $hashKey
     * @param string $value
     * @return bool|int
     * coding_date 2019/10/13 21:42
     * developer YangYunTian
     */
    public function h_set($dir='', $key='', $hashKey='', $value='') {
        if(empty($dir) || empty($key) || empty($hashKey)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->hSet($key, $hashKey, $value);
    }

    

    /**
     * Hash类型 整数相加
     * @param string $dir
     * @param string $key
     * @param string $hashKey
     * @param int $number
     * @return bool|int
     * coding_date 2019/10/13 21:43
     * developer YangYunTian
     */
    public function h_incr($dir='', $key='', $hashKey='', $number=1) {
        if(empty($dir) || empty($key) || empty($hashKey)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->hIncrBy($key, $hashKey, $number);
    }

    /**
     * Hash类型 是否存在
     * @param string $dir
     * @param string $key
     * @param string $hashKey
     * @return bool
     * coding_date 2019/10/13 21:47
     * developer YangYunTian
     */
    public function h_exists($dir='', $key='', $hashKey='') {
        if(empty($dir) || empty($key) || empty($hashKey)) return false;
        $key = $this->parseKey($dir, $key);
        return self::$redis->hExists($key, $hashKey);
    }

    /**
     * Hash类型  存在直接返回不存在则读数据库
     * @param string $dir
     * @param string $key
     * @param string $hashKey
     * @param array $options
     * @param $func
     * @return bool|string
     * coding_date 2019/10/13 21:48
     * developer YangYunTian
     */
    public function h_get_or_set($dir='', $key='', $hashKey='', $options=[], $func) {
        if(empty($dir) || empty($key) || empty($hashKey)) return false;
        if(!$this->h_exists($dir, $key, $hashKey)) {
            $value = $func(self::$redis, $options);
            $this->h_set($dir, $key, $hashKey, $value);
            return $value;
        }
        return $this->h_get($dir, $key, $hashKey);
    }
}